@typeparam TItem
@using Microsoft.JSInterop
@using Radzen.Blazor.Rendering
@using System.Globalization
@using System.Collections
@using Radzen

@if (RowIndex == Column.GetLevel())
{
    <th rowspan="@(Column.GetRowSpan())" colspan="@(Column.GetColSpan())" @attributes="@Attributes" class="@CssClass" scope="col" style="@GetStyle()" @onmouseup=@(args => Grid.EndColumnReorder(args, ColumnIndex))>
        <div @onclick='@((args) => Grid.OnSort(args, Column))' @onkeydown="OnSortKeyPressed">
            @if ((Grid.AllowColumnReorder && Column.Reorderable || Grid.AllowGrouping && Column.Groupable))
            {
                <span id="@(Grid.getColumnUniqueId(ColumnIndex) + "-drag")" class="rz-column-drag"
                @onclick:preventDefault="true" @onclick:stopPropagation="true"
                @onmousedown:preventDefault="true"
                @onmousedown=@(args => Grid.StartColumnReorder(args, ColumnIndex, Column.UniqueID ?? Column.Property))></span>
            }
            <span class="rz-column-title" title="@(Grid.ShowColumnTitleAsTooltip ? @Column.GetTitle() : Column.HeaderTooltip)">
                @if (Column.HeaderTemplate != null)
                {
                    <span class="@Column.GetHeaderClass()" @onkeydown:stopPropagation>@Column.HeaderTemplate</span>
                }
                else
                {
                    <span class="@Column.GetHeaderClass()">@Column.GetTitle()</span>
                }

                @if (Grid.AllowSorting && Column.Sortable)
                {
                    @if (Column.GetSortOrder() == SortOrder.Ascending)
                    {
                        <span class="notranslate rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-asc"></span>
                        @if(Grid.ShowMultiColumnSortingIndex)
                        {
                            <RadzenBadge BadgeStyle="BadgeStyle.Info" Shade="Shade.Lighter" IsPill=true Text="@Column.getSortIndexAsString()" />
                        }
                    }
                    else if (Column.GetSortOrder() == SortOrder.Descending)
                    {
                        <span class="notranslate rz-sortable-column-icon rzi-grid-sort rzi-sort rzi-sort-desc"></span>
                        @if(Grid.ShowMultiColumnSortingIndex)
                        {
                            <RadzenBadge BadgeStyle="BadgeStyle.Info" Shade="Shade.Lighter" IsPill=true Text="@Column.getSortIndexAsString()" />
                        }
                    }
                    else
                    {
                        <span class="notranslate rz-sortable-column-icon rzi-grid-sort rzi-sort"></span>
                    }
                }
            </span>
            @if (Grid.AllowColumnResize && Column.Resizable && Column.Parent == null)
            {
                <div id="@(Grid.getColumnUniqueId(ColumnIndex) + "-resizer")" style="cursor:col-resize;float:right;"
                @onclick:preventDefault="true" @onclick:stopPropagation="true" class="rz-column-resizer"
                @onmousedown:preventDefault="true"
                @onmousedown=@StartColumnResize @onmouseup=@StopColumnResize>&nbsp;</div>
            }
            @{var filterMode = Column.FilterMode ?? Grid.FilterMode;}
            @if (Grid.AllowFiltering && Column.Filterable && (filterMode == FilterMode.Advanced || filterMode == FilterMode.CheckBoxList))
            {
                <i @ref=@filterButton @onclick:stopPropagation="true" @onmousedown=@ToggleFilter
                class="@getFilterIconCss(Column)" onclick=@getFilterOpen() @onclick:preventDefault="true">
                    @Grid.FilterIcon
                </i>

                <Popup Lazy=@(Grid.FilterPopupRenderMode == PopupRenderMode.OnDemand) @ref=popup id="@($"{Column.GetColumnPopupID()}")" class="rz-overlaypanel"
                style="display:none;min-width:250px;" @onkeydown="OnFilterPopupKeyPressed">
                    <div class="rz-overlaypanel-content">
                        @if (Column.FilterTemplate != null)
                        {
                            @Column.FilterTemplate(Column)
                        }
                        else
                        {
                            <form id="@($"{Column.GetColumnPopupID()}-form")" @onsubmit="@(args => ApplyFilter())" class="rz-grid-filter">
                                @if (filterMode == FilterMode.Advanced)
                                {
                                    <span class="rz-grid-filter-label">@Grid.FilterText</span>
                                    <RadzenDropDown InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Grid.FilterOperatorAriaLabel + Column.GetFilterOperatorText(Column.GetSecondFilterOperator()) }})"
                                    @onclick:preventDefault="true" Data="@(Column.GetFilterOperators().Select(t => new { Value = Column.GetFilterOperatorText(t), Key = t }))" TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" Value="@Column.GetFilterOperator()" Change="@(args => Column.SetFilterOperator((FilterOperator)args))" />
                                    @if (Column.FilterValueTemplate != null)
                                    {
                                        @Column.FilterValueTemplate(Column)
                                    } 
                                    else if (PropertyAccess.IsNullableEnum(Column.FilterPropertyType) || PropertyAccess.IsEnum(Column.FilterPropertyType))
                                    {
                                        <RadzenDropDown Disabled="@(!Column.CanSetFilterValue())" AllowClear="false" AllowFiltering="false" TValue="@object"
                                        Value=@Column.GetFilterValue() Multiple="false" Placeholder="@Grid.EnumFilterSelectText" TextProperty="Text" ValueProperty="Value" Data=@EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(Column.FilterPropertyType) ?? Column.FilterPropertyType, Grid.EnumFilterTranslationFunc)
                                        Change="@(args => Column.SetFilterValue(args))"
                                        InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel  + Column.GetFilterValue() }})" />
                                    }
                                    else if (PropertyAccess.IsNumeric(Column.FilterPropertyType))
                                    {
                                        @(Grid.DrawNumericFilter(Column, false))
                                    }
                                    else if (PropertyAccess.IsDate(Column.FilterPropertyType))
                                    {
                                        <RadzenDatePicker Disabled="@(!Column.CanSetFilterValue())" TValue="@object" ShowTime="@Column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
                                        Value="@Column.GetFilterValue()" Change="@(args => Column.SetFilterValue(PropertyAccess.IsDateOnly(Column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value))" AllowInput=@(Grid.AllowFilterDateInput)
                                        InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel  + Column.GetFilterValue() }})" />

                                    }
                                    else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
                                    {
                                        <RadzenCheckBox Disabled="@(!Column.CanSetFilterValue())" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel  + Column.GetFilterValue() }})" TriState="true" TValue="@object" Value="@Column.GetFilterValue()" Change="@(args => { Column.SetFilterValue(null); Column.SetFilterValue(args); Grid.SaveSettings(); })" />
                                    }
                                    else
                                    {
                                        <RadzenTextBox Disabled="@(!Column.CanSetFilterValue())" id="@($"{Column.GetColumnPopupID()}-sf")" aria-label=@(Column.Title + Grid.FilterValueAriaLabel + Column.GetFilterValue()) Value="@($"{Column.GetFilterValue()}")" Change="@(args => Column.SetFilterValue(args))" />
                                    }

                                    <RadzenDropDown @onclick:preventDefault="true" TextProperty="Text" ValueProperty="Value" Style="width: 90px" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.LogicalOperatorAriaLabel + (Column.LogicalFilterOperator == LogicalFilterOperator.And ? Grid.AndOperatorText : Grid.OrOperatorText) }})"
                                    Data="@(Enum.GetValues(typeof(LogicalFilterOperator)).Cast<LogicalFilterOperator>().Select(t => new { Text = t == LogicalFilterOperator.And ? Grid.AndOperatorText : Grid.OrOperatorText, Value = t }))" TValue="LogicalFilterOperator" Value="@Column.LogicalFilterOperator" Change="@(args => Column.SetLogicalFilterOperator((LogicalFilterOperator)args))" />

                                    <RadzenDropDown InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Grid.SecondFilterOperatorAriaLabel + Column.GetFilterOperatorText(Column.GetSecondFilterOperator()) }})" @onclick:preventDefault="true" Data="@(Column.GetFilterOperators().Select(t => new { Value = Column.GetFilterOperatorText(t), Key = t }))" TextProperty="Value" ValueProperty="Key" TValue="FilterOperator" Value="@Column.GetSecondFilterOperator()" Change="@(args => Column.SetSecondFilterOperator((FilterOperator)args))" />
                                    @if (Column.SecondFilterValueTemplate != null)
                                    {
                                        @Column.SecondFilterValueTemplate(Column)
                                    } 
                                    else if (PropertyAccess.IsNullableEnum(Column.FilterPropertyType) || PropertyAccess.IsEnum(Column.FilterPropertyType))
                                    {
                                        <RadzenDropDown Disabled="@(!Column.CanSetFilterValue(false))" AllowClear="false" AllowFiltering="false" TValue="@object" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.SecondFilterValueAriaLabel }})"
                                        Value=@Column.GetSecondFilterValue() Multiple="false" Placeholder="@Grid.EnumFilterSelectText" TextProperty="Text" ValueProperty="Value" Data=@EnumExtensions.EnumAsKeyValuePair(Nullable.GetUnderlyingType(Column.FilterPropertyType) ?? Column.FilterPropertyType, Grid.EnumFilterTranslationFunc)
                                        Change="@(args => Column.SetFilterValue(args,false))" />
                                    }
                                    else if (PropertyAccess.IsNumeric(Column.FilterPropertyType))
                                    {
                                        @(Grid.DrawNumericFilter(Column, false, false))
                                    }
                                    else if (PropertyAccess.IsDate(Column.FilterPropertyType))
                                    {
                                        <RadzenDatePicker Disabled="@(!Column.CanSetFilterValue(false))" TValue="@object" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title +  Grid.SecondFilterValueAriaLabel + Column.GetSecondFilterValue() }})"
                                        ShowTime="@Column.ShowTimeForDateTimeFilter()" ShowTimeOkButton="true" DateFormat="@Grid.getFilterDateFormat(Column)"
                                        Value="@Column.GetSecondFilterValue()" Change="@(args => Column.SetFilterValue(PropertyAccess.IsDateOnly(Column.FilterPropertyType) ? PropertyAccess.DateOnlyFromDateTime(args.Value) : args.Value, false))" AllowInput=@(Grid.AllowFilterDateInput) />

                                    }
                                    else if (Column.FilterPropertyType == typeof(bool) || Column.FilterPropertyType == typeof(bool?))
                                    {
                                        <RadzenCheckBox Disabled="@(!Column.CanSetFilterValue(false))" InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title +  Grid.SecondFilterValueAriaLabel  + Column.GetSecondFilterValue() }})" TriState="true" TValue="@object" Value="@Column.GetSecondFilterValue()" Change="@(args => { Column.SetFilterValue(args, false); Grid.SaveSettings(); })" />
                                    }
                                    else
                                    {
                                        <RadzenTextBox Disabled="@(!Column.CanSetFilterValue(false))" id="@($"{Column.GetColumnPopupID()}-sf2")" aria-label=@(Column.Title + Grid.SecondFilterValueAriaLabel + Column.GetSecondFilterValue()) Value="@($"{Column.GetSecondFilterValue()}")" Change="@(args => Column.SetFilterValue(args, false))" />
                                    }
                                }
                                else
                                {
                                    @if (Column.FilterValueTemplate != null)
                                    {
                                        @Column.FilterValueTemplate(Column)
                                    } 
                                    else
                                    {
                                        <RadzenProgressBarCircular Style="position:absolute;width:100%;" Visible="@isLoading" Value="100" ShowValue="false" Mode="ProgressBarMode.Indeterminate" />
                                        <RadzenListBox AllowVirtualization="@Column.AllowCheckBoxListVirtualization" AllowClear="true" Multiple="true" Style="height: 300px"
                                        TValue="IEnumerable" Value=@(Column.GetFilterValue() as IEnumerable) Change="@ListBoxChange" 
                                        Data=@filterValues Count=@filterValuesCount LoadData="@LoadFilterValues" 
                                        AllowFiltering="@(!string.IsNullOrEmpty(Column.GetFilterProperty()))"
                                        Disabled="@(!Column.CanSetFilterValue())" FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
                                        InputAttributes="@(new Dictionary<string,object>(){ { "aria-label", Column.Title + Grid.FilterValueAriaLabel  + Column.GetFilterValue() }})">
                                            <Template>
                                                @if (context as Enum != null)
                                                {
                                                    @EnumExtensions.GetDisplayDescription(context as Enum, Grid.EnumFilterTranslationFunc)
                                                }
                                                else
                                                {
                                                    @(!string.IsNullOrEmpty(Column.FormatString) ? string.Format(Column.FormatProvider ?? Grid?.Culture ?? CultureInfo.CurrentCulture, Column.FormatString, context ?? "") : Convert.ToString(context ?? "", Grid?.Culture ?? CultureInfo.CurrentCulture))
                                                }
                                            </Template>
                                        </RadzenListBox>
                                    }
                                }
                            </form>
                        }
                    </div>
                    @if (Column.FilterTemplate == null)
                    {
                        <div class="rz-grid-filter-buttons">
                            <RadzenButton ButtonStyle="ButtonStyle.Base" class="rz-clear-filter" Click="@ClearFilter" Text=@Grid.ClearFilterText title="@Grid.ClearFilterText" />
                            <RadzenButton onmousedown="@getBlur()" ButtonStyle="ButtonStyle.Primary" class="rz-apply-filter" form="@($"{Column.GetColumnPopupID()}-form")" ButtonType="ButtonType.Submit" Text=@Grid.ApplyFilterText title="@Grid.ApplyFilterText" />
                        </div>
                    }
                </Popup>
            }
        </div>
        @if (Grid.allColumns.Any(c => c.Parent != null) && Grid.AllowFiltering && Column.Filterable && (filterMode == FilterMode.Simple || filterMode == FilterMode.SimpleWithMenu))
        {
            @Grid.RenderSimpleFilter(Column, filterMode)
        }
    </th>
}
else
{
    @foreach(var column in Grid.childColumns.Where(c => c.GetVisible() && c.Parent == Column))
    {
        ColumnIndex = Grid.allColumns.IndexOf(column);//for child must have different columnindex

        <RadzenDataGridHeaderCell RowIndex="@RowIndex" Grid="@Grid" Column="@column" Style="@column.GetStyle(true, true)" ColumnIndex="@ColumnIndex"
        CssClass="@($"rz-unselectable-text {(Grid.AllowSorting && column.Sortable ? "rz-sortable-column" : "")} {column.HeaderCssClass} {Grid.getFrozenColumnClass(column, Grid.ColumnsCollection.Where(c => c.GetVisible()).ToList())} {Grid.getCompositeCellCSSClass(column)} {Grid.getColumnAlignClass(column)}".Trim())" />
    }
}
@code {
    Radzen.Blazor.Rendering.Popup popup;
    ElementReference filterButton;

    int filterValuesCount;
    internal IEnumerable filterValues;
    string loadDataArgsString;
    bool isLoading = false;

    async Task LoadFilterValues(LoadDataArgs loadDataArgs)
    {
        isLoading = true;

        await Task.Yield();

        var property = Column.Property != Column.FilterProperty && !string.IsNullOrEmpty(Column.FilterProperty) ? Column.Property :
            Column.GetFilterProperty();

        var propertyType = PropertyAccess.GetPropertyType(typeof(TItem), property) ?? Column.FilterPropertyType;

        var loadDataArgsString = $"{loadDataArgs.Skip}|{loadDataArgs.Top}{loadDataArgs.Filter}";

        if (Column.Grid.LoadColumnFilterData.HasDelegate)
        {
            var args = new DataGridLoadColumnFilterDataEventArgs<TItem>() { Property = property, Column = Column, Filter = loadDataArgs.Filter, Skip = loadDataArgs.Skip, Top = loadDataArgs.Top };

            await Column.Grid.LoadColumnFilterData.InvokeAsync(args);

            filterValues = !string.IsNullOrEmpty(args.Property) ? 
                args.Data.AsQueryable().Select(property).Distinct() : args.Data;
            filterValuesCount = args.Count;
        }
        else if(!string.IsNullOrEmpty(property) && (filterValues == null || this.loadDataArgsString != loadDataArgsString) && Column.Grid.Data != null)
        {
            this.loadDataArgsString = loadDataArgsString;

            IQueryable query;

            if(!string.IsNullOrEmpty(loadDataArgs.Filter))
            {
                query = (Column.Grid.childData.Any() ? Column.Grid.GetSelfRefView(Column.Grid.Data.AsQueryable(), "") :
                            Column.Grid.Data.AsQueryable())
                            .Where<TItem>(Column.AlwaysShowAllCheckBoxListData ? 
                                Enumerable.Empty<RadzenDataGridColumn<TItem>>() : 
                                    Column.Grid.allColumns.Where(c => c != Column));

                if (Column.Property != Column.FilterProperty && !string.IsNullOrEmpty(Column.FilterProperty))
                {
                    query = QueryableExtension.Where(query, new FilterDescriptor[] {
                        new FilterDescriptor()
                        {
                            Property = Column.Property,
                            FilterProperty = Column.FilterProperty,
                            FilterValue = loadDataArgs.Filter,
                            FilterOperator = FilterOperator.Contains
                        } },
                            LogicalFilterOperator.Or, FilterCaseSensitivity.CaseInsensitive);
                }
                else
                {
                    query = query.Where(property, loadDataArgs.Filter, StringFilterOperator.Contains, FilterCaseSensitivity.CaseInsensitive);
                }
            }
            else
            {
                query = (Column.Grid.childData.Any() ? Column.Grid.GetSelfRefView(Column.Grid.Data.AsQueryable(), "") :
                    Column.Grid.Data.AsQueryable()).Where<TItem>(Column.AlwaysShowAllCheckBoxListData ?
                                Enumerable.Empty<RadzenDataGridColumn<TItem>>() :
                                    Column.Grid.allColumns.Where(c => c != Column));
            }

            if (Column.Property != Column.FilterProperty && !string.IsNullOrEmpty(Column.FilterProperty))
            {
                query = query.SelectMany(property).Select(Column.FilterProperty).Distinct().Cast<object>().OrderBy(i => i);
                propertyType = query.ElementType;
            }
            else
            {
                query = query.Select(property).Distinct().Cast<object>().OrderBy(i => i);
            }

            filterValuesCount = query.Cast<object>().Count();

            if(loadDataArgs.Skip != null)
            {
                query = query.Cast<object>().Skip(loadDataArgs.Skip.Value);
            }

            if(loadDataArgs.Top != null)
            {
                query = query.Cast<object>().Take(loadDataArgs.Top.Value);
            }

            filterValues = await Task.FromResult(Column.Grid.childData.Any() ?
                query.Cast<object>().ToList().AsQueryable().Cast(propertyType) : query.Cast(propertyType));

            if (!Column.AllowCheckBoxListVirtualization)
            {
                await InvokeAsync(StateHasChanged);
            }
        }

        isLoading = false;
    }

    void ListBoxChange(object args)
    {
        var enumerable = args as IEnumerable;

        Type propertyType = null;

        if (Column.Property != Column.FilterProperty && !string.IsNullOrEmpty(Column.FilterProperty))
        {
            var collectionType =  PropertyAccess.GetPropertyType(typeof(TItem), Column.Property);
            if (collectionType != null && collectionType.IsGenericType)
            {
                var itemType = collectionType.GenericTypeArguments.FirstOrDefault();
                if(itemType != null)
                {
                    propertyType = PropertyAccess.GetPropertyType(itemType, Column.FilterProperty);
                }
            }
        }
        else
        {
            propertyType = PropertyAccess.GetPropertyType(typeof(TItem), Column.GetFilterProperty());
        }

        if (propertyType == null)
        {
            propertyType = Column.FilterPropertyType;
        }

        Column.SetFilterValue(enumerable.Cast<object>().Any() ? propertyType != null ? enumerable.AsQueryable().Cast(propertyType) : enumerable : null);
    }

    string getFilterOpen()
    {
        return Grid.FilterPopupRenderMode == PopupRenderMode.Initial ? $"Radzen.togglePopup(this, '{Column.GetColumnPopupID()}', false, null, null, true, true)" : "";
    }

    async Task ToggleFilter()
    {
        if (Grid.FilterPopupRenderMode == PopupRenderMode.OnDemand)
        {
            await popup.ToggleAsync(filterButton);

            Grid.allColumns
            .Where(c => c.GetVisible() && c.UniqueID != Column.UniqueID)
            .Select(c => c.headerCell).ToList()
            .ForEach(cell => InvokeAsync(cell.CloseFilter));
        }
    }

    async Task ClearFilter()
    {
        if (Grid.FilterPopupRenderMode == PopupRenderMode.OnDemand)
        {
            await popup.CloseAsync();
        }
        await Grid.ClearFilter(Column, true);
    }

    string getBlur()
    {
        return IsAdvancedNumeric() ? "Radzen.blur(this, event)" : null;
    }

    bool IsAdvancedNumeric()
    {
        return (Column.FilterMode ?? Grid.FilterMode) == FilterMode.Advanced &&
            PropertyAccess.IsNumeric(Column.FilterPropertyType) &&
                !(PropertyAccess.IsEnum(Column.FilterPropertyType) || PropertyAccess.IsNullableEnum(Column.FilterPropertyType));
    }

    async Task ApplyFilter()
    {
        if (IsAdvancedNumeric())
        {
            var targetType = Nullable.GetUnderlyingType(Column.FilterPropertyType) ?? Column.FilterPropertyType;

            if (Column.FilterValueTemplate == null)
            {
                var firstInputValue = await Grid.GetJSRuntime().InvokeAsync<string>("Radzen.getNumericValue", Grid.getFilterInputId(Column) + "f");
                if (!object.Equals($"{Column.GetFilterValue()}", $"{firstInputValue}"))
                {
                    Column.SetFilterValue(!string.IsNullOrEmpty(firstInputValue) ? Convert.ChangeType(firstInputValue, targetType) : null);
                }
            }

            if (Column.SecondFilterValueTemplate == null)
            {
                var secondInputValue = await Grid.GetJSRuntime().InvokeAsync<string>("Radzen.getNumericValue", Grid.getFilterInputId(Column) + "s");
                if (!object.Equals($"{Column.GetSecondFilterValue()}", $"{secondInputValue}"))
                {
                    Column.SetFilterValue(!string.IsNullOrEmpty(secondInputValue) ? Convert.ChangeType(secondInputValue, targetType) : null, false);
                }
            }
        }

        if (Grid.FilterPopupRenderMode == PopupRenderMode.OnDemand)
        {
            await popup.CloseAsync();
        }
        await Grid.ApplyFilter(Column, true);
    }

    [Parameter(CaptureUnmatchedValues = true)]
    public IReadOnlyDictionary<string, object> Attributes { get; set; }

    [Parameter]
    public RadzenDataGridColumn<TItem> Column { get; set; }

    [Parameter]
    public int ColumnIndex { get; set; }

    [Parameter]
    public int RowIndex { get; set; }

    [Parameter]
    public RadzenDataGrid<TItem> Grid { get; set; }

    [Parameter]
    public string CssClass { get; set; }

    [Parameter]
    public string Style { get; set; }

    private string GetStyle()
    {
        var styles = (new List<string>() { Column.GetStyle(true, true), Style }).Distinct().ToList();

        if (Attributes?.TryGetValue("style", out var styleAttribute) == true)
        {
            styles.Add(Convert.ToString(styleAttribute));
        }

        var finalStyle = string.Join(";",
                styles
                .Select(x => x?.Trim().TrimEnd(';'))
                .Where(x => !string.IsNullOrEmpty(x))
            );

        return finalStyle;
    }

    private string getFilterIconCss(RadzenDataGridColumn<TItem> column)
    {
        var additionalStyle = Column.HasActiveFilter() ? "rz-grid-filter-active" : "";
        return $"notranslate rzi rz-grid-filter-icon {additionalStyle}";
    }

    private Task OnSortKeyPressed(KeyboardEventArgs args)
    {
        var key = args.Code ?? args.Key;
        if (key == "Enter")
        {
            return Grid.OnSort(args, Column);
        }
        return Task.CompletedTask;
    }

    protected override void OnParametersSet()
    {
        base.OnParametersSet();

        if (Column != null)
        {
            Column.headerCell = this;
        }
    }

    internal async Task CloseFilter()
    {
        if (popup != null)
        {
            await popup.CloseAsync(filterButton);
        }
    }

    async Task StartColumnResize(MouseEventArgs args)
    {
        if(args.Button == 0) 
        { 
            await Grid.StartColumnResize(args, ColumnIndex);
        }
    }

    async Task StopColumnResize(MouseEventArgs args)
    {
        if (args.Button == 0)
        {
            await Grid.StopColumnResize(args, ColumnIndex);
        }
    }

    internal async Task OpenFilter()
    {
        if (Grid.FilterPopupRenderMode == PopupRenderMode.OnDemand)
        {
            await popup.ToggleAsync(filterButton);
        }
        else
        {
            await Grid.GetJSRuntime().InvokeVoidAsync("Radzen.togglePopup", filterButton, Column.GetColumnPopupID(), false, null, null, true, true);
        }
    }

    async Task OnFilterPopupKeyPressed(KeyboardEventArgs args)
    {
        var key = args.Code ?? args.Key;
        if (key == "Escape")
        {
            await CloseFilter();
            await ClearFilter();
            await Grid.GetJSRuntime().InvokeVoidAsync("Radzen.focusElement", Grid.GridId());
        }
    }
}
